import time, threading
def work(num):
    print('线程名称：',threading.current_thread().getName(),'参数：',num,'开始时间：',time.strftime('%Y-%m-%d %H:%M:%S'))

class MyThread(threading.Thread):
    def __init__(self,num):
        super().__init__()
        self.num = num
    def run(self):
        print('线程名称：', threading.current_thread().getName(), '参数：', self.num, '开始时间：', time.strftime('%Y-%m-%d %H:%M:%S'))
# if __name__ == '__main__':
    # 构造器方式
    # print('主线程开始时间：', time.strftime('%Y-%m-%d %H:%M:%S'))
    # t1 = threading.Thread(target=work, args=(3,))
    # t2 = threading.Thread(target=work, args=(2,))
    # t3 = threading.Thread(target=work, args=(1,))
    # t1.start()
    # t2.start()
    # t3.start()
    # t1.join()
    # t2.join()
    # t3.join()
    # print('主线程结束时间：', time.strftime('%Y-%m-%d %H:%M:%S'))

    # 继承方式
    # print('主线程开始时间：', time.strftime('%Y-%m-%d %H:%M:%S'))
    # t1 = MyThread(3)
    # t2 = MyThread(2)
    # t3 = MyThread(1)
    # t1.start()
    # t2.start()
    # t3.start()
    # t1.join()
    # t2.join()
    # t3.join()
    # print('主线程结束时间：', time.strftime('%Y-%m-%d %H:%M:%S'))

# TODO 守护线程
# 不设置守护线程
# def work(num):
#     for i in range(num):
#         print(threading.current_thread().name + "  " + str(i))
# t = threading.Thread(target=work, args=(10,), name='守护线程')
# t.start()
# for i in range(10):
#     pass

# 设置守护线程
# def work(num):
#     for i in range(num):
#         print(threading.current_thread().name + "  " + str(i))
# t = threading.Thread(target=work, args=(10,), name='守护线程')
# t.daemon = True
# t.start()
# for i in range(10):
#     pass
'''
如果你设置一个线程为守护线程，就表示这个线程是不重要的，在进程退出的时候，不用等待这个线程退出；如果你的主线程在退出的时候，
不用等待哪些子线程完成，那就设置这些线程为守护线程；如果你想等待子线程完成后再退出，那就什么都不用做，或者显示地将 daemon 属性设置为 false
'''

# TODO 线程本地数据
# 不使用 threading.local
# num = 0
# def work():
#     global num
#     for i in range(10):
#         num += 1
#     print(threading.current_thread().getName(), num)
#     time.sleep(0.0001)
# for i in range(5):
#     threading.Thread(target=work).start()
'''
上面示例中 num 是全局变量，变成了公共资源，通过输出结果，我们发现子线程之间的计算结果出现了互相干扰的情况
'''
# 使用 threading.local
# num = threading.local()
# def work():
#     num.x = 0
#     for i in range(10):
#         num.x += 1
#     print(threading.current_thread().getName(), num.x)
#     time.sleep(0.0001)
# for i in range(5):
#     threading.Thread(target=work).start()
'''
使用 threading.local 的示例中，num 是全局变量，但每个线程定义的属性 num.x 是各自线程独有的，其它线程是不可见的，因此每个线程的计算结果未出现相互干扰的情况
'''

# TODO 定时器
from threading import Timer
# def work():
#     print("Hello Python")
# # 5 秒后执行 work 方法
# t = Timer(5, work)
# t.start()

# 重复执行
count = 0
def work():
    print('当前时间：', time.strftime('%Y-%m-%d %H:%M:%S'))
    global t, count
    count += 1
    # 如果 count 小于 5，开始下一次调度
    if count < 5:
        t = Timer(1, work)
        # 取消调度
        # t.cancel()
        t.start()
# 指定 2 秒后执行 work 方法
t = Timer(2, work)

t.start()

'''
1）threading.Thread 实例的方法、属性

方法	说明
start()	启动线程活动，它在一个线程里最多只能被调用一次。
run()	表示线程活动的方法。
join(timeout=None)	等待至线程中止。
getName()	返回线程名。
setName()	设置线程名。
is_alive()	返回线程是否是活动的。
daemon	是否为守护线程的标志。
ident	线程标识符，线程尚未开始返回 None，已启动返回非零整数。

2）threading 直接调用的方法

方法	说明
active_count()	返回当前存活的线程类 Thread 对象，返回个数等于 enumerate() 返回的列表长度。
current_thread()	返回当前对应调用者的 Thread 对象。
get_ident()	返回当前线程的线程标识符，它是一个非零的整数。
enumerate()	以列表形式返回当前所有存活的 Thread 对象。
main_thread()	返回主 Thread 对象。
settrace(func)	为所有 threading 模块开始的线程设置追踪函数。
setprofile(func)	为所有 threading 模块开始的线程设置性能测试函数。
stack_size([size])	返回创建线程时用的堆栈大小。
'''